package com.cloudfun.campusshare.listener;

import com.alibaba.fastjson.JSON;
import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.constant.DelayMsgType;
import com.cloudfun.campusshare.common.constant.RabbitConstants;
import com.cloudfun.campusshare.common.exception.BusinessException;
import com.cloudfun.campusshare.common.model.dto.dingtalk.TextContent;
import com.cloudfun.campusshare.sender.DelayMessage;
import com.cloudfun.campusshare.service.DingTalkService;
import com.cloudfun.campusshare.service.handler.DelayMessageHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : zhangyongjie
 * @version : 1.0
 * @createTime : 2020/6/18 18:37
 * @description : 延时任务消费
 */
@Component
@Slf4j
public class DelayMessageListener {
    private Map<DelayMsgType, DelayMessageHandler> handles = new HashMap<>();

    @Autowired
    private DingTalkService dingTalkService;

    @Autowired
    public void injectDelayMsgHandler(List<DelayMessageHandler> list) {
        for (DelayMessageHandler delayMessageHandler : list) {
            handles.put(delayMessageHandler.support(), delayMessageHandler);
        }
    }

    @RabbitListener(queues = RabbitConstants.Queue.DELAY_QUEUE_NAME)
    public void handle(String message) {
        log.info("接收到延时消息：message ->{}", message);
        DelayMessage delayMessage = JSON.parseObject(message, DelayMessage.class);
        try {
            boolean processSuccess = false;
            for (int i = 0; i < 5; i++) {
                try {
                    handles.get(delayMessage.getType()).handleMessage(delayMessage);
                    processSuccess = true;
                    break;
                } catch (ObjectOptimisticLockingFailureException oplfe) {
                    log.error("延时消息消费失败：{}, 处理时乐观锁异常", message, oplfe);
                }
            }
            if (!processSuccess) {
                throw new BusinessException(Code.ERROR, "乐观锁失败，且超过最大重试次数：" + 5);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("延时消息消费失败，参数:{}", message, e);
            dingTalkService.sendMessage(new TextContent("延时消息消费失败，参数:" + message));
        }
    }
}
